home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / tutorials / geometer / geom.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  27.5 KB  |  1,118 lines

  1. /*
  2.  * Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17.  
  18. #include "parse.h"
  19. #include <gl.h>
  20. #include <device.h>
  21. #include <math.h>
  22. #include <stream.h>
  23. #include <sys/types.h>
  24. #include <sys/stat.h>
  25. #include "generic.h"
  26. #include "gizmo.h"
  27. #include <getopt.h>
  28. #include <unistd.h>
  29.  
  30. reservedword currentlinetype = _segment;
  31. void handleredraw();
  32. void initshowcaseui();
  33. void setselect();
  34.  
  35. float pbsize;
  36.  
  37. float fxmin = -1.0, fxmax = 1.0;
  38. float fymin = -1.0, fymax = 1.0;
  39. extern long     xorg, yorg, xsize, ysize;
  40. extern long    linecount, layerset;
  41.  
  42. primitive *plist = 0, *plisttail = 0;
  43. primitive *pselected = 0;
  44.  
  45. /* primssame() determines whether the primitives are the same --
  46.  * same type, same constraints, ...  This routine only does a
  47.  * correct check on primitives entered via the buttons.
  48.  */
  49.  
  50. long primssame(primitive *p, primitive *q)
  51. {
  52.     primitive *p1, *p2, *p3, *q1, *q2, *q3;
  53.  
  54.     if (p->ptype == _comment || p->ptype == _text ||
  55.         p->ptype == _length) return 0;
  56.     constrainttype ct = p->c.type;
  57.     if (ct != q->c.type) return 0;
  58.     switch (ct) {
  59.     case VERTFREE:
  60.     case VERTONLINE:
  61.     case VERTONCIRCLE:
  62.     case VERTONCONIC:
  63.         return 0;
  64.     case VERTLINELINE:
  65.     case VERTVERTVERTMID:
  66.     case LINEVERTVERT:
  67.         if ((p->c.p1 != q->c.p1 || p->c.p2 != q->c.p2) &&
  68.             (p->c.p1 != q->c.p2 || p->c.p2 != q->c.p1)) return 0;
  69.         break;
  70.     case VERTLINECIRC1:
  71.     case VERTLINECIRC2:
  72.     case VERTCIRCCIRC1:
  73.     case VERTCIRCCIRC2:
  74.     case LINEVERTLINEPAR:
  75.     case LINEVERTLINEPERP:
  76.     case LINEVERTCIRC1:
  77.     case LINEVERTCIRC2:
  78.     case LINECIRCCIRCEXT1:
  79.     case LINECIRCCIRCEXT2:
  80.     case CIRCVERTVERT:
  81.         if (p->c.p1 != q->c.p1 || p->c.p2 != q->c.p2) return 0;
  82.         break;
  83.     case CIRCVERTVERTVERT:
  84.         p1 = p->c.p1, p2 = p->c.p2, p3 = p->c.p3;
  85.         q1 = q->c.p1, q2 = q->c.p2, q3 = q->c.p3;
  86.         if (!((p1 == q1 && p2 == q2 && p3 == q3) ||
  87.             (p1 == q2 && p2 == q1 && p3 == q3) ||
  88.             (p1 == q1 && p2 == q3 && p3 == q2) ||
  89.             (p1 == q3 && p2 == q2 && p3 == q1) ||
  90.             (p1 == q2 && p2 == q3 && p3 == q1) ||
  91.             (p1 == q3 && p2 == q1 && p3 == q2))) return 0;
  92.         break;
  93.     default:
  94.         if (p->c.p1 != q->c.p1 || p->c.p2 != q->c.p2 ||
  95.         p->c.p3 != q->c.p3 || p->c.p4 != q->c.p4 ||
  96.         p->c.p5 != q->c.p5) return 0;
  97.         break;
  98.     }
  99.     if (p->Color != q->Color || p->layers != q->layers) return 0;
  100.     return 1;
  101. }
  102.  
  103. void addprimitive(primitive *p)
  104. {
  105.     for (primitive *p1 = plist; p1; p1 = p1->next) {
  106.     if (primssame(p, p1)) {
  107.         delete p;
  108.             removeentry(restable, p->st->symbol);
  109.         message("Duplicate primitive -- not added", 0, 0, 0);
  110.         setselect();
  111.         return;
  112.     }
  113.     }
  114.     setdirtyfile();
  115.     if (plisttail) {
  116.     plisttail->next = p;
  117.     plisttail = p;
  118.     } else
  119.     plist = plisttail = p;
  120. }
  121.  
  122. void clearplist()
  123. {
  124.     while (plist) {
  125.     primitive *p = plist->next;
  126.     delete plist;
  127.     plist = plist->next;
  128.     }
  129.     plisttail = pselected = 0;
  130.     linecount = 1;
  131. }
  132.  
  133. void zoomworld(float zoom)
  134. {
  135.     vertex *v;
  136.  
  137.     for (primitive *p = plist; p; p = p->next) {
  138.     switch (p->c.type) {
  139.         case VERTFREE:
  140.         case VERTONLINE:
  141.         case VERTONCIRCLE:
  142.         case VERTONCONIC:
  143.             v = (vertex *)p;
  144.         v->xw *= zoom;
  145.         v->yw *= zoom;
  146.         break;
  147.         default:
  148.             break;
  149.     }
  150.     p->satisfied = 0;
  151.     }
  152. }
  153.  
  154. void moveworld(long dx, long dy)
  155. {
  156.     vertex *v;
  157.  
  158.     for (primitive *p = plist; p; p = p->next) {
  159.     switch (p->c.type) {
  160.         case VERTFREE:
  161.         case VERTONLINE:
  162.         case VERTONCIRCLE:
  163.         case VERTONCONIC:
  164.             v = (vertex *)p;
  165.         v->xw += .01*dx;
  166.         v->yw += .01*dy;
  167.         break;
  168.         default:
  169.             break;
  170.     }
  171.     p->satisfied = 0;
  172.     }
  173. }
  174.  
  175. static long appliedconstraint;
  176.  
  177. void checkconstraint(primitive *p)
  178. {
  179.     line *l, *l1;
  180.     vertex *v, *v1, *v2;
  181.     circle *c;
  182.     bezier *b;
  183.     conic *con, *cnc;
  184.     length *len1, *len2, *len3;
  185.     float dx, dy, radd, rad;
  186.  
  187.     if (p->c.type != VERTFREE && p->c.p1 == 0) {
  188.     p->satisfied = 1;
  189.     return;
  190.     }
  191.     switch(p->c.type) {
  192.     case VERTFREE:
  193.         break;
  194.     case LINEVERTVERT:
  195.         l = (line *)p;
  196.         if (p->c.p1->satisfied == 0 || p->c.p2->satisfied == 0)
  197.             return;
  198.         l->v1 = *(vertex *)p->c.p1;
  199.         l->v2 = *(vertex *)p->c.p2;
  200.         homogenizeline(l);
  201.         break;
  202.     case VERTLINELINE:
  203.         if (p->c.p1->satisfied == 0 || p->c.p2->satisfied == 0)
  204.             return;
  205.         vertonlineline((vertex *)p, (line *)p->c.p1, (line *)p->c.p2);
  206.         break;
  207.     case VERTONLINE:
  208.         if (p->c.p1->satisfied == 0)
  209.             return;
  210.         v = (vertex *)p;
  211.         l = (line *)p->c.p1;
  212.         v->projecttoline(l);
  213.         break;
  214.     case VERTONCONIC:
  215.         if (p->c.p1->satisfied == 0)
  216.             return;
  217.         v = (vertex *)p;
  218.         con = (conic *)p->c.p1;
  219.         projecttoconic(v, con);
  220.         break;
  221.     case VERTLINEVERTMIRROR:
  222.         if (p->c.p1->satisfied == 0 || p->c.p2->satisfied == 0)
  223.             return;
  224.         vlvmirror((vertex *)p);
  225.             break;
  226.     case VERTONCIRCLE:
  227.         if (p->c.p1->satisfied == 0)
  228.             return;
  229.         v = (vertex *)p;
  230.         c = (circle *)p->c.p1;
  231.         dx = v->xw - c->center.xw;
  232.         dy = v->yw - c->center.yw;
  233.         radd = c->radius/sqrt(dx*dx + dy*dy);
  234.         v->xw = c->center.xw + dx*radd;
  235.         v->yw = c->center.yw + dy*radd;
  236.         break;
  237.     case VERTCIRCCENTER:
  238.         if (p->c.p1->satisfied == 0)
  239.             return;
  240.         v = (vertex *)p;
  241.         c = (circle *)p->c.p1;
  242.         v->xw = c->center.xw;
  243.         v->yw = c->center.yw;
  244.         break;
  245.     case VERTVERTVERTMID:
  246.         if (p->c.p1->satisfied == 0 || p->c.p2->satisfied == 0)
  247.             return;
  248.         v = (vertex *)p;
  249.         v1 = (vertex *)p->c.p1;
  250.         v2 = (vertex *)p->c.p2;
  251.         if (v1->w == 0.0) { v->w = 0; v->xw = v1->xw; v->yw = v1->yw; break; }
  252.         if (v2->w == 0.0) { v->w = 0; v->xw = v2->xw; v->yw = v2->yw; break; }
  253.         v->xw = (v1->xw + v2->xw)/2.0;
  254.         v->yw = (v1->yw + v2->yw)/2.0;
  255.         v->w = 1.0;
  256.         break;
  257.     case LINEVERTLINEPERP:
  258.         if (p->c.p1->satisfied == 0 || p->c.p2->satisfied == 0)
  259.             return;
  260.         l = (line *)p;
  261.         v = (vertex *)p->c.p1;
  262.         l1 = (line *)p->c.p2;
  263.         l->XW = -l1->YW; l->YW = l1->XW;
  264.         l->W = l1->YW*v->xw - l1->XW*v->yw;
  265.         l->v1 = *v;
  266.         l->v2.xw = -l->YW; l->v2.yw = l->XW; l->v2.w = 0.0;
  267.         break;
  268.     case LINEVERTLINEPAR:
  269.         if (p->c.p1->satisfied == 0 || p->c.p2->satisfied == 0)
  270.             return;
  271.         l = (line *)p;
  272.         v = (vertex *)p->c.p1;
  273.         l1 = (line *)p->c.p2;
  274.         l->XW = l1->XW; l->YW = l1->YW;
  275.         l->W = -(l->XW*v->xw + l->YW*v->yw);
  276.         l->v1 = *v;
  277.         l->v2.xw = -l->YW; l->v2.yw = l->XW; l->v2.w = 0.0;
  278.         break;
  279.     case CIRCVERTVERT:
  280.         if (p->c.p1->satisfied == 0 || p->c.p2->satisfied == 0)
  281.             return;
  282.         v = (vertex *)p->c.p1;
  283.         v1 = (vertex *)p->c.p2;
  284.         rad = vvdist(v, v1);
  285.         c = (circle *)p;
  286.         c->center.xw = v->xw;
  287.         c->center.yw = v->yw;
  288.         c->center.w = v->w;
  289.         c->radius = rad;
  290.         break;
  291.     case VERTLINECIRC1:
  292.     case VERTLINECIRC2:
  293.         if (p->c.p1->satisfied == 0 || p->c.p2->satisfied == 0)
  294.             return;
  295.         l = (line *)p->c.p1;
  296.         v1 = (vertex *)&l->v1;
  297.         v2 = (vertex *)&l->v2;
  298.         c = (circle *)p->c.p2;
  299.         v = (vertex *)p;
  300.         solvevlc(l, c, v, (p->c.type == VERTLINECIRC1) ? 1 : 2);
  301.         break;
  302.     case VERTLINECONIC1:
  303.     case VERTLINECONIC2:
  304.         if (p->c.p1->satisfied == 0 || p->c.p2->satisfied == 0)
  305.             return;
  306.         vert_lineconic((vertex *)p);
  307.         break;
  308.     case LINEVERTCIRC1:
  309.     case LINEVERTCIRC2:
  310.         if (p->c.p1->satisfied == 0 || p->c.p2->satisfied == 0)
  311.             return;
  312.         line_vertcircletan((line *)p);
  313.         break;
  314.     case LINECIRCCIRCEXT1:
  315.     case LINECIRCCIRCEXT2:
  316.         if (p->c.p1->satisfied == 0 || p->c.p2->satisfied == 0)
  317.             return;
  318.         line_circcircleext((line *)p);
  319.         break;
  320.     case LINECIRCCIRCINT1:
  321.     case LINECIRCCIRCINT2:
  322.         if (p->c.p1->satisfied == 0 || p->c.p2->satisfied == 0)
  323.             return;
  324.         line_circcircleint((line *)p);
  325.         break;
  326.     case VERTCIRCCIRC1:
  327.     case VERTCIRCCIRC2:
  328.         if (p->c.p1->satisfied == 0 || p->c.p2->satisfied == 0)
  329.             return;
  330.         vert_circcircle((vertex *)p);
  331.         break;
  332.     case CIRCLINELINELINE1:
  333.     case CIRCLINELINELINE2:
  334.     case CIRCLINELINELINE3:
  335.     case CIRCLINELINELINE4:
  336.         if (p->c.p1->satisfied == 0 || p->c.p2->satisfied == 0 ||
  337.                 p->c.p3->satisfied == 0)
  338.             return;
  339.         circle_lll((circle *)p);
  340.         break;
  341.     case CIRCVERTVERTVERT:
  342.         if (p->c.p1->satisfied == 0 || p->c.p2->satisfied == 0 ||
  343.                 p->c.p3->satisfied == 0)
  344.             return;
  345.         circle_vvv((circle *)p);
  346.         break;
  347.     case CIRCCIRCCIRCINV:
  348.         if (p->c.p1->satisfied == 0 || p->c.p2->satisfied == 0)
  349.             return;
  350.         circle_ccinvert((circle *)p);
  351.         break;
  352.     case VERTCIRCVERTINV:
  353.         if (p->c.p1->satisfied == 0 || p->c.p2->satisfied == 0)
  354.             return;
  355.         v_vcinvert((vertex *)p);
  356.         break;
  357.     case CIRCLINECIRCINV:
  358.         if (p->c.p1->satisfied == 0 || p->c.p2->satisfied == 0)
  359.             return;
  360.         circle_linecinvert((circle *)p);
  361.         break;
  362.     case BEZVERTVERTVERTVERT:
  363.         if (p->c.p1->satisfied == 0 || p->c.p2->satisfied == 0 ||
  364.                 p->c.p3->satisfied == 0 || p->c.p4->satisfied == 0)
  365.             return;
  366.         b = (bezier *)p;
  367.         b->v1 = *(vertex *)p->c.p1;
  368.         b->v2 = *(vertex *)p->c.p2;
  369.         b->v3 = *(vertex *)p->c.p3;
  370.         b->v4 = *(vertex *)p->c.p4;
  371.         break;
  372.     case RATIOVERTVERTVERT:
  373.         if (p->c.p1->satisfied == 0 || p->c.p2->satisfied == 0 ||
  374.                 p->c.p3->satisfied == 0)
  375.             return;
  376.         ratio_vvv((length *)p);
  377.         break;
  378.     case VERTVERTVERTRATIO:
  379.         if (p->c.p1->satisfied == 0 || p->c.p2->satisfied == 0 ||
  380.                 p->c.p3->satisfied == 0)
  381.             return;
  382.         v_vvratio((vertex *)p);
  383.         break;
  384.     case LENVERTVERT:
  385.         if (p->c.p1->satisfied == 0 || p->c.p2->satisfied == 0)
  386.             return;
  387.         v1 = (vertex *)p->c.p1;
  388.         v2 = (vertex *)p->c.p2;
  389.         len1 = (length *)p;
  390.         len1->value = vvdist(v1, v2);
  391.         break;
  392.     case CIRCVERTLEN:
  393.         if (p->c.p1->satisfied == 0 || p->c.p2->satisfied == 0)
  394.             return;
  395.         v = (vertex *)p->c.p1;
  396.         len1 = (length *)p->c.p2;
  397.         c = (circle *)p;
  398.         c->center.xw = v->xw;
  399.         c->center.yw = v->yw;
  400.         c->center.w = v->w;
  401.         c->radius = len1->value;
  402.         break;
  403.     case LENPLUSLENLEN:
  404.         if (p->c.p1->satisfied == 0 || p->c.p2->satisfied == 0)
  405.             return;
  406.         len1 = (length *)p->c.p1;
  407.         len2 = (length *)p->c.p2;
  408.         len3 = (length *)p;
  409.         len3->value = len1->value + len2->value;
  410.         break;
  411.     case LENMINUSLENLEN:
  412.         if (p->c.p1->satisfied == 0 || p->c.p2->satisfied == 0)
  413.             return;
  414.         len1 = (length *)p->c.p1;
  415.         len2 = (length *)p->c.p2;
  416.         len3 = (length *)p;
  417.         len3->value = len1->value - len2->value;
  418.         break;
  419.     case LENTIMESLENLEN:
  420.         if (p->c.p1->satisfied == 0 || p->c.p2->satisfied == 0)
  421.             return;
  422.         len1 = (length *)p->c.p1;
  423.         len2 = (length *)p->c.p2;
  424.         len3 = (length *)p;
  425.         len3->value = len1->value * len2->value;
  426.         break;
  427.     case LENDIVLENLEN:
  428.         if (p->c.p1->satisfied == 0 || p->c.p2->satisfied == 0)
  429.             return;
  430.         len1 = (length *)p->c.p1;
  431.         len2 = (length *)p->c.p2;
  432.         len3 = (length *)p;
  433.         if (len2->value != 0.0)
  434.             len3->value = len1->value / len2->value;
  435.         else
  436.             len3->value = 1.0e30;
  437.         break;
  438.     case LENANGLE:
  439.         if (p->c.p1->satisfied == 0) return;
  440.         ((length *)p)->value = ((length *)p->c.p1)->value;
  441.         break;
  442.     case ANGLEVERTVERTVERT:
  443.         if (p->c.p1->satisfied == 0 || p->c.p2->satisfied == 0 ||
  444.                 p->c.p3->satisfied == 0)
  445.             return;
  446.         a_vvv((length *)p);
  447.         break;
  448.     case VERTANGLEVERTVERT:
  449.         if (p->c.p1->satisfied == 0 || p->c.p2->satisfied == 0 ||
  450.                 p->c.p3->satisfied == 0)
  451.             return;
  452.         v_avv((vertex *)p);
  453.         break;
  454.     case CONICFIVEVERT:
  455.         if (p->c.p1->satisfied == 0 || p->c.p2->satisfied == 0 ||
  456.                 p->c.p3->satisfied == 0 || p->c.p4->satisfied == 0 ||
  457.         p->c.p5->satisfied == 0)
  458.             return;
  459.         cnc = (conic *)p;
  460.         conic_vvvvv(cnc);
  461.         break;
  462.     case CONICFIVELINE:
  463.         if (p->c.p1->satisfied == 0 || p->c.p2->satisfied == 0 ||
  464.                 p->c.p3->satisfied == 0 || p->c.p4->satisfied == 0 ||
  465.         p->c.p5->satisfied == 0)
  466.             return;
  467.         cnc = (conic *)p;
  468.         conic_lllll(cnc);
  469.         break;
  470.     case LINETANGENTCONIC1:
  471.     case LINETANGENTCONIC2:
  472.         if (p->c.p1->satisfied == 0 || p->c.p2->satisfied == 0)
  473.             return;
  474.         l = (line *)p;
  475.         linetangenttoconic(l);
  476.         break;
  477.     }
  478.     p->satisfied = 1;
  479.     appliedconstraint = 1;
  480. }
  481.  
  482. void checkconstraints()
  483. {
  484.     long hit;
  485.  
  486.     if (pselected) {
  487.     pselected->satisfied = 0;
  488.     do {
  489.         hit = 0;
  490.         for (primitive *p = plist; p; p = p->next) {
  491.         if (p->satisfied && p->c.p1 && p->c.p1->satisfied == 0) {
  492.             hit = 1;
  493.             p->satisfied = 0;
  494.         } else
  495.         if (p->satisfied && p->c.p2 && p->c.p2->satisfied == 0) {
  496.             hit = 1;
  497.             p->satisfied = 0;
  498.         } else
  499.         if (p->satisfied && p->c.p3 && p->c.p3->satisfied == 0) {
  500.             hit = 1;
  501.             p->satisfied = 0;
  502.         } else
  503.         if (p->satisfied && p->c.p4 && p->c.p4->satisfied == 0) {
  504.             hit = 1;
  505.             p->satisfied = 0;
  506.         }
  507.         if (p->satisfied && p->c.p5 && p->c.p5->satisfied == 0) {
  508.             hit = 1;
  509.             p->satisfied = 0;
  510.         }
  511.         }
  512.     } while (hit == 1);
  513.     }
  514. //    for (primitive *p = plist; p; p = p->next)
  515. //        p->satisfied = 0;
  516.     do {
  517.         appliedconstraint = 0;
  518.         for (primitive *p = plist; p; p = p->next)
  519.         if (p->satisfied == 0) checkconstraint(p);
  520.     } while (appliedconstraint == 1);
  521.     for (primitive *p = plist; p; p = p->next)
  522.         if (p->satisfied == 0) {
  523.         displaymessage("Wacko constraints");
  524.     }
  525. }
  526.  
  527. long isconstrained(primitive *pp)
  528. {
  529.     for (primitive *p = plist; p; p = p->next) {
  530.     if (p->c.p1 == pp || p->c.p2 == pp || p->c.p3 == pp)
  531.         return 1;
  532.     }
  533.     return 0;
  534. }
  535.  
  536. void deleteprimitive(primitive *pp)
  537. {
  538.     if (isconstrained(pp)) {
  539.     displaymessage("Sorry, it's constrained");
  540.     return;
  541.     }
  542.     if (pp == pselected) pselected = 0;
  543.     if (pp == plist) {
  544.     plist = plist->next;
  545.     if (plist == 0) plisttail = 0;
  546.     } else for (primitive *p = plist; p; p = p->next) {
  547.     if (p->next == pp) {
  548.         p->next = pp->next;
  549.         if (pp == plisttail) plisttail = p;
  550.     }
  551.     }
  552.     /* stuff to free? XXX */
  553.     removeentry(restable, pp->st->symbol);
  554.     delete pp;
  555. }
  556.  
  557. void selectvertex(float fx, float fy)
  558. {
  559.     vertex              *v;
  560.     short               x, y;
  561.  
  562.     if (v = hitvertex(fx, fy)) {
  563.         pselected = v;
  564.     drawmode(PUPDRAW); color(0); clear(); drawmode(NORMALDRAW);
  565.     while (getbutton(LEFTMOUSE)) {
  566.         x = (short)getvaluator(MOUSEX);
  567.         y = (short)getvaluator(MOUSEY);
  568.         getpoint(&fx, &fy, x, y);
  569.         if (fx > .999*fxmax) fx = .999*fxmax;
  570.         if (fx < -.999*fxmax) fx = -.999*fxmax;
  571.         if (fy > .999*fymax) fy = .999*fymax;
  572.         if (fy < -.999*fymax) fy = -.999*fymax;
  573.         v->xw = fx; v->yw = fy; v->w = 1.0;
  574.         v->satisfied = 0;
  575.         drawgeom();
  576.     }
  577.     drawmode(PUPDRAW); color(0); clear(); drawmode(NORMALDRAW);
  578.     } else {
  579.         pselected = hitprimitive(fx, fy);
  580.     }
  581.     while (getbutton(LEFTMOUSE))
  582.             ;   // do nothing -- just wait.
  583.     qreset();
  584. }
  585.  
  586. main(int argc, char **argv)
  587. {
  588.     int ch;
  589.  
  590.     while ((ch = getopt(argc, argv, "fv")) != -1)
  591.     switch (ch) {
  592.         case 'f':        /* foreground */
  593.         foreground_flag = 1;
  594.         break;
  595.         case 'v':            /* view-only */
  596.         VIEW_ONLY = view_only = 1;
  597.         break;
  598.         case '?':
  599.         fprintf(stderr, "usage: %s [-fv] [file]\n", argv[0]);
  600.         exit(-1);
  601.     }
  602.     MAKE_BACKUPS = MAKE_CHECKPOINTS = 0;    /* OPTIONAL */
  603.     initialize();
  604.     inittables();
  605.     if (argc - optind >= 1)
  606.         doopen(argv[optind]);
  607.     else if (VIEW_ONLY) {
  608.     fprintf(stderr, "You must name a file in view-only mode\n");
  609.     exit(-1);
  610.     }
  611.     /*initsignal();                           /* OPTIONAL */
  612.     /*opengizmo(GIZMO_MASTER);                /* OPTIONAL */
  613.     makewintitle();
  614.     getwindowinfo();
  615.     recalcsizes();
  616.     makepulldown();                         /* OPTIONAL - must follow winopen */
  617.     mainloop();
  618. }
  619.  
  620. vertex *hitvertex(float fx, float fy)
  621. {
  622.     vertex *v;
  623.     
  624.     for (primitive *p = plist; p; p = p->next) {
  625.     if (p->ptype == _vertex && (p->layers&layerset)) {
  626.         v = (vertex *)p;
  627.         if (v->hitvertex(fx, fy)) return (vertex *)p;
  628.     }
  629.     }
  630.     return (vertex *)0;
  631. }
  632.  
  633. line *hitline(float fx, float fy)
  634. {
  635.     line *l;
  636.     
  637.     for (primitive *p = plist; p; p = p->next) {
  638.     if (p->ptype == _line) {
  639.         l = (line *)p;
  640.         if (l->hitline(fx, fy)) return (line *)p;
  641.     }
  642.     }
  643.     return (line *)0;    
  644. }
  645.  
  646. line *hitanotherline(float fx, float fy, primitive *ll)
  647. {
  648.     line *l;
  649.     
  650.     for (primitive *p = plist; p; p = p->next) {
  651.     if (p->ptype == _line && (p != ll)) {
  652.         l = (line *)p;
  653.         if (l->hitline(fx, fy)) return (line *)p;
  654.     }
  655.     }
  656.     return (line *)0;    
  657. }
  658.  
  659. circle *hitcircle(float fx, float fy)
  660. {
  661.     circle *c;
  662.     
  663.     for (primitive *p = plist; p; p = p->next) {
  664.     if (p->ptype == _circle) {
  665.         c = (circle *)p;
  666.         if (c->hitcircle(fx, fy)) return (circle *)p;
  667.     }
  668.     }
  669.     return (circle *)0;    
  670. }
  671.  
  672. circle *hitanothercircle(float fx, float fy, primitive *cc)
  673. {
  674.     circle *c;
  675.     
  676.     for (primitive *p = plist; p; p = p->next) {
  677.     if (p->ptype == _circle && (p != cc)) {
  678.         c = (circle *)p;
  679.         if (c->hitcircle(fx, fy)) return (circle *)p;
  680.     }
  681.     }
  682.     return (circle *)0;    
  683. }
  684.  
  685. primitive *hitprimitive(float fx, float fy)
  686. {
  687.     line *l;
  688.     vertex *v;
  689.     circle *c;
  690.     bezier *bez;
  691.     conic *con;
  692.  
  693.     for (primitive *p = plist; p; p = p->next) {
  694.         if (layerset & p->layers) switch (p->ptype) {
  695.         case _line:
  696.             l = (line *)p;
  697.         if (l->hitline(fx, fy)) return p;
  698.         break;
  699.         case _vertex:
  700.         v = (vertex *)p;
  701.         if (v->hitvertex(fx, fy)) return p;
  702.         break;
  703.         case _circle:
  704.         c = (circle *)p;
  705.         if (c->hitcircle(fx, fy)) return p;
  706.         break;
  707.         case _bezier:
  708.         bez = (bezier *)p;
  709.         if (bez->hitbezier(fx, fy)) return p;
  710.         break;
  711.         case _conic:
  712.             con = (conic *)p;
  713.         if (con->hitconic(fx, fy)) return p;
  714.         break;
  715.     }
  716.     }
  717.     return (primitive *)0;    
  718. }
  719.  
  720. void showcomment()
  721. {
  722.     long linecount = 0;
  723.     char sysstring[60];
  724.     mode_t omask = umask(0);
  725.     FILE *fp = fopen("geom.com", "w");
  726.     umask(omask);
  727.     if (fp == 0) {
  728.         displaymessage("Couldn't open geom.com");
  729.     return;
  730.     }
  731.     for (primitive *p = plist; p; p = p->next)
  732.         if (p->ptype == _text) {
  733.         fprintf(fp, "%s\n", ((comment *)p)->str);
  734.         linecount++;
  735.     }
  736.     if (linecount == 0) {
  737.     fprintf(fp, "The clown who wrote this example neglected to\n");
  738.     fprintf(fp, "provide any documentation.\n");
  739.     linecount = 2;
  740.     }
  741.     fprintf(fp, "\nTo exit, hold down either alt-key and press 'q'\n");
  742.     linecount += 2;
  743.     fclose(fp);
  744.     long zipsize = 16*linecount;
  745.     if (zipsize < 250) zipsize = 250;
  746.     sprintf(sysstring, "jot -v -F8 -p200,900,%d,700 geom.com", 680-zipsize);
  747.     system(sysstring);
  748. }
  749.  
  750. long smearflag = 0;
  751.  
  752. void drawgeom()
  753. {
  754.     float ym = 0.0;
  755.     float yinfo = fymin + 8*2.3*pbsize;
  756.     vertex *v;
  757.     line *l;
  758.     circle *c;
  759.     conic *con;
  760.     bezier *b;
  761.     length *ll;
  762.     text *tt;
  763.  
  764.     checkconstraints();
  765.     font(0);    /* XXX shouldn't need this!!! */
  766.     pushviewport();
  767.     pushmatrix();
  768.     viewport(0, (short)(xsize-UIWIDTH-1), 0, (short)(ysize-PULLDOWNHEIGHT-1));
  769.     ortho2(fxmin, fxmax, fymin, fymax);    
  770.     initscreen();
  771.     for (primitive *p = plist; p; p = p->next)
  772.         if (layerset & p->layers) switch (p->ptype) {
  773.         case _vertex:
  774.         v = (vertex *)p;
  775.         v->draw();
  776.         if (smearflag && v->Color == SMEAR)
  777.             v->PostScript(stdout);
  778.         break;
  779.         case _line:
  780.         l = (line *)p;
  781.         l->draw();
  782.         if (smearflag && l->Color == SMEAR)
  783.             l->PostScript(stdout);
  784.         break;
  785.         case _circle:
  786.         c = (circle *)p;
  787.         c->draw();
  788.         if (smearflag && c->Color == SMEAR)
  789.             c->PostScript(stdout);
  790.         break;
  791.             case _conic:
  792.             con = (conic *)p;
  793.         con->draw();
  794.         if (smearflag && con->Color == SMEAR)
  795.             con->PostScript(stdout);
  796.         break;
  797.         case _bezier:
  798.             b = (bezier *)p;
  799.         b->draw();
  800.         if (smearflag && b->Color == SMEAR)
  801.             b->PostScript(stdout);
  802.         break;
  803.         case _length:
  804.             ll = (length *)p;
  805.         if (ll->name[0] == 0) break;
  806.         cmov2(-.99, ym); ym -= 2.3*pbsize;
  807.         ll->draw();
  808.         if (smearflag && ll->Color == SMEAR)
  809.             ll->PostScript(stdout);
  810.         break;
  811.         case _text:
  812.             tt = (text *)p;
  813.         //if (tt->str[0] == 0) break;
  814.         cmov2(-.99, yinfo); yinfo -= 2.3*pbsize;
  815.         tt->draw();
  816.         break;
  817.     }
  818.     drawpulldown();
  819.     swapbuffers();
  820.     popviewport();
  821.     popmatrix();
  822. }
  823.  
  824. long vnumber = 1;
  825.  
  826. void genname(primitive *p)
  827. {
  828.     long i = 1;
  829.     char *str, s[100];
  830.  
  831.     switch (p->ptype) {
  832.     case _vertex: str = "v"; break;
  833.     case _line: str = "l"; break;
  834.     case _circle: str = "c"; break;
  835.     case _bezier: str = "bez"; break;
  836.     case _conic: str = "con"; break;
  837.     }
  838.     do {
  839.     sprintf(s, "%s%d", str, i++);
  840.     } while (lookup(idtable, s));
  841.     symtableentry *st = addentry(idtable, s, p->ptype);
  842.     st->p = p; p->st = st;
  843. }
  844.  
  845. vertex *makevertex(float x, float y)
  846. {
  847.     vertex *v = new vertex;
  848.     genname(v);
  849.     sprintf(v->name, "%d", vnumber++);
  850.     v->xw = x; v->yw = y; v->w = 1.0;
  851.     pselected = v;
  852.     return v;
  853. }
  854.  
  855. void initscreen()
  856. {
  857.     color(BLACK);
  858.     clear();
  859.     color(WHITE);
  860. }
  861.  
  862. void recalcsizes()
  863. {
  864.     initshowcaseui();
  865.     if (xsize-UIWIDTH < ysize-PULLDOWNHEIGHT) {
  866.     fxmin = -1.0; fxmax = 1.0;
  867.     fymax = ((float)(ysize-PULLDOWNHEIGHT))/(xsize-UIWIDTH);
  868.     fymin = -fymax;
  869.         pbsize = 12.0/(xsize-UIWIDTH);
  870.     } else {
  871.         fymin = -1.0; fymax = 1.0;
  872.     fxmax = ((float) (xsize-UIWIDTH))/(ysize-PULLDOWNHEIGHT);
  873.     fxmin = -fxmax;
  874.         pbsize = 12.0/(ysize-PULLDOWNHEIGHT);
  875.     }
  876. }
  877.  
  878. short oldr, oldg, oldb;
  879. extern int gd;
  880.  
  881. void initialize()
  882. {
  883.     if (foreground_flag) foreground();
  884.     prefposition(20, 755+UIWIDTH, 20, 755);
  885. //    prefposition(20, 755+UIWIDTH, 220, 955);
  886.     winopen("geometry");
  887.     gd = (int)qgetfd();
  888.     winconstraints();
  889.     doublebuffer();
  890.     gconfig();
  891.     qdevice(LEFTARROWKEY); qdevice(UPARROWKEY);
  892.     qdevice(DOWNARROWKEY); qdevice(RIGHTARROWKEY);
  893.     qdevice(PAGEUPKEY); qdevice(PAGEDOWNKEY);
  894.     qdevice(LEFTMOUSE);
  895.     qdevice(MIDDLEMOUSE);
  896.     qdevice(KEYBD);
  897.     qdevice(MOUSEX); qdevice(MOUSEY);
  898.     qdevice(WINQUIT); qdevice(WINSHUT);
  899.     getmcolor(255, &oldr, &oldg, &oldb);
  900.     mapcolor(255, 255, 255, 0);
  901.     blink(25, 255, 0, 0, 0);
  902.     glcompat(GLC_MQUEUERATE, GLC_COMPATRATE);
  903. }
  904.  
  905. void restore255()
  906. {
  907.     blink(0, 255, oldr, oldg, oldb);
  908.     mapcolor(255, oldr, oldg, oldb);
  909.     gflush();
  910. }
  911.  
  912. void getpoint(float *x, float *y, long sx, long sy)
  913. {
  914.     *x = 2.0*fxmax*(sx - xorg)/(xsize-UIWIDTH) + fxmin; 
  915.     *y = 2.0*fymax*(sy - yorg)/(ysize-PULLDOWNHEIGHT) +fymin;
  916. }
  917.  
  918. line *linevertvert(vertex *v1, vertex *v2)
  919. {
  920.     line *l = new line;
  921.     genname(l);
  922.     l->c.p1 = v1; l->c.p2 = v2;
  923.     l->type = currentlinetype;
  924.     l->c.type = LINEVERTVERT;
  925.     pselected = l;
  926.     return l;
  927. }
  928.  
  929. vertex *vertvertvertmid(vertex *v1, vertex *v2)
  930. {
  931.     vertex *v = new vertex;
  932.     genname(v);
  933.     v->c.p1 = v1; v->c.p2 = v2;
  934.     v->c.type = VERTVERTVERTMID;
  935.     v->type = _plus;
  936.     pselected = v;
  937.     return v;    
  938. }
  939.  
  940. circle *circvertvert(vertex *v1, vertex *v2)
  941. {
  942.     circle *c = new circle;
  943.     genname(c);
  944.     c->c.p1 = v1; c->c.p2 = v2;
  945.     c->c.type = CIRCVERTVERT;
  946.     pselected = c;
  947.     return c;
  948. }
  949.  
  950. vertex *vertlineline(line *l1, line *l2)
  951. {
  952.     vertex *v = new vertex;
  953.     genname(v);
  954.     v->c.type = VERTLINELINE;
  955.     v->c.p1 = l1; v->c.p2 = l2;
  956.     v->type = _plus;
  957.     pselected = v;
  958.     return v;
  959. }
  960.  
  961. void verttoline(vertex *v1, line *l1)
  962. {
  963.     v1->c.p1 = l1;
  964.     v1->c.type = VERTONLINE;
  965.     v1->type = _cross;
  966. }
  967.  
  968. void verttocirc(vertex *v1, circle *c1)
  969. {
  970.     v1->c.p1 = c1;
  971.     v1->c.type = VERTONCIRCLE;
  972.     v1->type = _cross;
  973. }
  974.  
  975. line *linevertlineperp(vertex *v, line *l1)
  976. {
  977.     line *l = new line;
  978.     genname(l);
  979.     l->c.p1 = v; l->c.p2 = l1;
  980.     l->type = currentlinetype;
  981.     l->c.type = LINEVERTLINEPERP;
  982.     pselected = l;
  983.     return l;    
  984. }
  985.  
  986. line *linevertlinepar(vertex *v, line *l1)
  987. {
  988.     line *l = new line;
  989.     genname(l);
  990.     l->c.p1 = v; l->c.p2 = l1;
  991.     l->type = currentlinetype;
  992.     l->c.type = LINEVERTLINEPAR;
  993.     pselected = l;
  994.     return l;    
  995. }
  996.  
  997. vertex *linecirctovert1(line *l, circle *c, float fx, float fy)
  998. {
  999.     vertex *v = new vertex;
  1000.     genname(v);
  1001.     v->c.type = VERTLINECIRC1;
  1002.     v->c.p1 = l; v->c.p2 = c;
  1003.     checkconstraint(v);
  1004.     float d1 = (v->xw - fx)*(v->xw - fx)+(v->yw-fy)*(v->yw-fy);
  1005.     v->c.type = VERTLINECIRC2;
  1006.     checkconstraint(v);
  1007.     float d2 = (v->xw - fx)*(v->xw - fx)+(v->yw-fy)*(v->yw-fy);
  1008.     if (d1 < d2) v->c.type = VERTLINECIRC1;
  1009.     v->type = _plus;
  1010.     pselected = v;
  1011.     return v;
  1012. }
  1013.  
  1014. line *vertcirctoline1(vertex *v, circle *c, float fx, float fy)
  1015. {
  1016.     line *l = new line;
  1017.     genname(l);
  1018.     l->c.type = LINEVERTCIRC1;
  1019.     l->c.p1 = v; l->c.p2 = c;
  1020.     l->type = currentlinetype;
  1021.     checkconstraint(l);
  1022.     float d1 = (l->v1.xw - fx)*(l->v1.xw - fx)+(l->v1.yw-fy)*(l->v1.yw-fy);
  1023.     float d2 = (l->v2.xw - fx)*(l->v2.xw - fx)+(l->v2.yw-fy)*(l->v2.yw-fy);
  1024.     l->c.type = LINEVERTCIRC2;
  1025.     checkconstraint(l);
  1026.     float d3 = (l->v1.xw - fx)*(l->v1.xw - fx)+(l->v1.yw-fy)*(l->v1.yw-fy);
  1027.     float d4 = (l->v2.xw - fx)*(l->v2.xw - fx)+(l->v2.yw-fy)*(l->v2.yw-fy);
  1028.     if ((d1<d3 && d1<d4) || (d2<d3 && d2<d4)) l->c.type = LINEVERTCIRC1;
  1029.     pselected = l;
  1030.     return l;
  1031. }
  1032.  
  1033. line *circcirctolineext1(circle *c1, circle *c2, float fx, float fy)
  1034. {
  1035.     line *l = new line;
  1036.     genname(l);
  1037.     l->c.type = LINECIRCCIRCEXT1;
  1038.     l->c.p1 = c1; l->c.p2 = c2;
  1039.     l->type = currentlinetype;
  1040.     checkconstraint(l);
  1041.     float d1 = (l->v1.xw - fx)*(l->v1.xw - fx)+(l->v1.yw-fy)*(l->v1.yw-fy);
  1042.     float d2 = (l->v2.xw - fx)*(l->v2.xw - fx)+(l->v2.yw-fy)*(l->v2.yw-fy);
  1043.     l->c.type = LINECIRCCIRCEXT2;
  1044.     checkconstraint(l);
  1045.     float d3 = (l->v1.xw - fx)*(l->v1.xw - fx)+(l->v1.yw-fy)*(l->v1.yw-fy);
  1046.     float d4 = (l->v2.xw - fx)*(l->v2.xw - fx)+(l->v2.yw-fy)*(l->v2.yw-fy);
  1047.     if ((d1<d3 && d1<d4) || (d2<d3 && d2<d4)) l->c.type = LINECIRCCIRCEXT1;
  1048.     pselected = l;
  1049.     return l;
  1050. }
  1051.  
  1052. line *circcirctolineint1(circle *c1, circle *c2, float fx, float fy)
  1053. {
  1054.     line *l = new line;
  1055.     genname(l);
  1056.     l->c.type = LINECIRCCIRCINT1;
  1057.     l->c.p1 = c1; l->c.p2 = c2;
  1058.     l->type = currentlinetype;
  1059.     checkconstraint(l);
  1060.     float d1 = (l->v1.xw - fx)*(l->v1.xw - fx)+(l->v1.yw-fy)*(l->v1.yw-fy);
  1061.     float d2 = (l->v2.xw - fx)*(l->v2.xw - fx)+(l->v2.yw-fy)*(l->v2.yw-fy);
  1062.     l->c.type = LINECIRCCIRCINT2;
  1063.     checkconstraint(l);
  1064.     float d3 = (l->v1.xw - fx)*(l->v1.xw - fx)+(l->v1.yw-fy)*(l->v1.yw-fy);
  1065.     float d4 = (l->v2.xw - fx)*(l->v2.xw - fx)+(l->v2.yw-fy)*(l->v2.yw-fy);
  1066.     if ((d1<d3 && d1<d4) || (d2<d3 && d2<d4)) l->c.type = LINECIRCCIRCINT1;
  1067.     pselected = l;
  1068.     return l;
  1069. }
  1070.  
  1071. vertex *circcirctovert1(circle *c1, circle *c2, float fx, float fy)
  1072. {
  1073.     vertex *v = new vertex;
  1074.     genname(v);
  1075.     v->c.type = VERTCIRCCIRC1;
  1076.     v->c.p1 = c1; v->c.p2 = c2;
  1077.     checkconstraint(v);
  1078.     float d1 = (v->xw - fx)*(v->xw - fx)+(v->yw-fy)*(v->yw-fy);
  1079.     v->c.type = VERTCIRCCIRC2;
  1080.     checkconstraint(v);
  1081.     float d2 = (v->xw - fx)*(v->xw - fx)+(v->yw-fy)*(v->yw-fy);
  1082.     if (d1 < d2) v->c.type = VERTCIRCCIRC1;
  1083.     v->type = _plus;
  1084.     pselected = v;
  1085.     return v;
  1086. }
  1087.  
  1088. vertex *circcirctovert2(circle *c1, circle *c2)
  1089. {
  1090.     vertex *v = new vertex;
  1091.     genname(v);
  1092.     v->c.type = VERTCIRCCIRC2;
  1093.     v->c.p1 = c1; v->c.p2 = c2;
  1094.     v->type = _plus;
  1095.     pselected = v;
  1096.     return v;
  1097. }
  1098.  
  1099. circle *vvvtocircle(vertex *v1, vertex *v2, vertex *v3)
  1100. {
  1101.     circle *c = new circle;
  1102.     genname(c);
  1103.     c->c.p1 = v1; c->c.p2 = v2; c->c.p3 = v3;
  1104.     c->c.type = CIRCVERTVERTVERT;
  1105.     pselected = c;
  1106.     return c;
  1107. }
  1108.  
  1109. conic *vvvvvtoconic(vertex *v1, vertex *v2, vertex *v3, vertex *v4, vertex *v5)
  1110. {
  1111.     conic *c = new conic;
  1112.     genname(c);
  1113.     c->c.p1 = v1; c->c.p2 = v2; c->c.p3 = v3, c->c.p4 = v4; c->c.p5 = v5;
  1114.     c->c.type = CONICFIVEVERT;
  1115.     pselected = c;
  1116.     return c;
  1117. }
  1118.